import createElement from "./CreateElement"
import patch from "./patch"
import Vnode from "./Vnode"
// 判断两个节点是否一样 （本质上比较 key）===> 这里就是 key 重要作用的根源
function sameVnode(vnode1, vnode2) {
    return vnode1.key === vnode2.key
}

// 参数：
// parentNode 是真实节点, oldCh,newCh 是虚拟节点数组
export default function updateChildren(parentNode, oldChNodes, newCh) {
    let oldCh = []
        // 把 children 里的每个节点 也变成 虚拟节点
    for (let i = 0; i < oldChNodes.length; i++) {
        let oldVnode = oldChNodes[i]
        if (oldVnode.sel === undefined) {
            oldVnode = Vnode(
                oldVnode.tagName.toLowerCase(), {},
                oldVnode.textContent,
                oldVnode.children,
                oldVnode,
            )
        }
        oldCh.push(oldVnode)
    }
    // 旧前  
    let oldStart = 0
    let oldStartNode = oldCh[oldStart]
        // 新前
    let newStart = 0
    let newStartNode = newCh[newStart]
        // 旧后
    let oldEnd = oldCh.length - 1
    let oldEndNode = oldCh[oldEnd]
        // 新后
    let newEnd = newCh.length - 1
    let newEndNode = newCh[newEnd]

    let keyMap = new Map()
    for (let i = oldStart; i <= oldEnd; i++) {
        keyMap.set(oldCh[i].key, i)
    }
    console.log('keyMap:', keyMap)

    while (oldStart <= oldEnd && newStart <= newEnd) {

        if (oldCh[oldStart] === undefined) {
            oldStartNode = oldCh[++oldStart]
        } else if (oldCh[oldEnd] === undefined) {
            oldEndNode = oldCh[--oldEnd]
        }
        // 双前
        else if (sameVnode(newStartNode, oldStartNode)) {
            console.log(newStartNode.key, oldStartNode.key)
            console.log('跑这里来了1')
                // patch 一下，防止有各自的子节点，虽然key 一样
                // 反正如果最后是一样，只会经历计算，不会修改dom,还是很快
            patch(newStartNode, oldStartNode)
            newStartNode.elm = oldStartNode.elm // 同步一下两个虚拟节点的 elm,这样才算真正 同步
            oldStartNode = oldCh[++oldStart]
            newStartNode = newCh[++newStart]
        }
        // 双后
        else if (sameVnode(newEndNode, oldEndNode)) {
            console.log('跑这里来了2')
            patch(newEndNode, oldEndNode)
            newEndNode.elm = oldEndNode.elm // 同步一下两个虚拟节点的 elm,这样才算真正 同步
            oldEndNode = oldCh[--oldEnd]
            newEndNode = newCh[--newEnd]
        }
        // 前后
        else if (sameVnode(newEndNode, oldStartNode)) {
            console.log('跑这里来了3')
            patch(newEndNode, oldStartNode)
            newEndNode.elm = oldStartNode.elm
                // 添加到 旧后的后面
            parentNode.insertBefore(oldStartNode.elm, oldEndNode.elm.nextSibling)
            oldStartNode = oldCh[++oldStart]
            newEndNode = newCh[--newEnd]
        }
        // 后前
        else if (sameVnode(newStartNode, oldEndNode)) {
            console.log('跑这里来了4')
            patch(newStartNode, oldEndNode)
            newStartNode.elm = oldEndNode.elm
                // 添加到 旧前的前面
            parentNode.insertBefore(oldEndNode.elm, oldStartNode.elm)
            newStartNode = newCh[++newStart]
            oldEndNode = oldCh[--oldEnd]
        }
        // 查找
        else {

            console.log('跑这里来了5')
                // 新头节点（newCh 中的第一个）
            let newChild = newCh[newStart]
            if (keyMap.has(newChild.key)) {
                // 存在
                let index = keyMap.get(newChild.key)
                patch(newCh[newStart], oldCh[index])
                newCh[newStart].elm = oldCh[index].elm
                parentNode.insertBefore(oldCh[index].elm, oldStartNode.elm)
                oldCh[index] = undefined // 只是将 oldCh数组的 虚拟节点 换为 undefined ,不会影响 真实的 dom 树结构
            } else {
                // 不存在，创建新的
                let vnode = createElement(newCh[newStart])
                parentNode.insertBefore(vnode, oldStartNode.elm)
            }
            newStartNode = newCh[++newStart]
        }
    }
    // 最后进行 添加或删除
    // oldCh 多
    if (oldStart <= oldEnd) {
        // 删除操作
        for (let i = oldStart; i <= oldEnd; i++) {
            console.log('mmm', oldCh[i].elm)
            parentNode.removeChild(oldCh[i].elm)
        }
    }
    // newCh 多
    else if (newStart <= newEnd) {
        // 添加操作
        let before = newCh[newEnd + 1].elm ? newCh[newEnd + 1].elm : null
            // newCh[newEnd + 1].elm 注意这是真实节点，如果 不为空，就是一个节点，那一定已经添加到 parentNode 中了，如果是 null,说明就直接在后面添加，在 parent
            // 节点的最后也是 null,符合。
        for (let i = newStart; i <= newEnd; i++) {
            parentNode.insertBefore(newCh[i].elm, before)
        }
    }
}